#import "ACEDrawingView.h"
#import "ACEDrawingTools.h"
#import "TcpClient.h"
#import "MBProgressController.h"
#import <QuartzCore/QuartzCore.h>
#import "ACEDrawingView+List.h"
#define kDefaultLineColor       [UIColor redColor]
#define kDefaultLineWidth       3.0f;
#define kDefaultLineAlpha       1.0f

// experimental code
#define PARTIAL_REDRAW          0

@interface ACEDrawingView ()
{
    CGPoint beginLocation;
    CGPoint currentLocation;
    CGPoint previousLocation;
}
@property (nonatomic, strong) NSMutableArray *pathArray;
@property (nonatomic, strong) NSMutableArray *bufferArray;
@property (nonatomic, strong) id<ACEDrawingTool> currentTool;
//@property (nonatomic, strong) UIImage *image;
@end

#pragma mark -

@implementation ACEDrawingView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self configure];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        //[self configure];
    }
    return self;
}

- (void)configure
{
    // init the private arrays
    self.pathArray = [NSMutableArray array];
    self.bufferArray = [NSMutableArray array];
    
    // set the default values for the public properties
    self.lineColor = kDefaultLineColor;
    self.lineWidth = kDefaultLineWidth;
    self.lineAlpha = kDefaultLineAlpha;
    
    // set the transparent background
  //  self.backgroundColor = [UIColor clearColor];
    
    self.buttonArr = [NSMutableArray array]; // 存储所有的按钮
    
    self.currentTool = [self toolWithCurrentSettings];
    [self.pathArray addObject:self.currentTool];
    [self  installDropDownListView];

}
-(void)drawButtonTalk
{
    int i = 0;
    if(![self.btnDataArr count]){
    [[MBProgressController sharedInstance] showTipsOnlyText:@"无交互信息!" AndDelay:1.5];
        PostNoticeObserver(NoticeKey_EventNull, nil);
    }
    for(NSDictionary *dic in self.btnDataArr){
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        CGFloat x = [dic[@"X"] floatValue];
        CGFloat y = [dic[@"Y"] floatValue];
        CGFloat w =  [dic[@"Width"] floatValue];
        CGFloat h =  [dic[@"Height"] floatValue];
        btn.frame = Frame(x/self.zoomX,y/self.zoomY,w/self.zoomX,h/self.zoomY);
             btn.layer.borderWidth = 3.0;
        btn.backgroundColor = [UIColor clearColor];
        btn.tag = SECTION_BTN_TAG_BEGIN + i;
        btn.layer.borderColor = [UIColor whiteColor].CGColor;
        [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:btn];
        [self.buttonArr addObject:btn];
        i++;
    }
}
-(void)forButtonHidden:(BOOL)hidd
{
 
   for(UIButton *btn in self.buttonArr){
       btn.hidden = hidd;
   }
  [self.buttonArr removeAllObjects];
}

#pragma mark - Drawing

- (void)drawRect:(CGRect)rect
{
#if PARTIAL_REDRAW
    // TODO: draw only the updated part of the image
    [self drawPath];
#else
   // UIGraphicsBeginImageContext(self.bounds.size);  //size 为CGSize类型，即你所需要的图片尺寸
//    CGRect r = self.bounds;
//    r.origin.x = 0;
//    r.origin.y = 0;
   // r.size.width = (Screen_Width-36)+self.nowX;
    [self.image drawInRect:self.bounds];
    //UIGraphicsEndImageContext();
    [self.currentTool draw];
#endif
}

- (void)updateCacheImage:(BOOL)redraw
{
    // init a context
//    CGRect r = self.bounds;
//    r.origin.x = 0;
//    r.origin.y = 0;
    UIGraphicsBeginImageContextWithOptions(self.bounds.size,NO, 0.0);
    
    if (redraw) {
        // erase the previous image
        self.image = nil;
        
        // I need to redraw all the lines
        for (id<ACEDrawingTool> tool in self.pathArray) {
            [tool draw];
        }
        
    } else {
        // set the draw point
//        NSLog(@"%f",CGPointZero.x);
//         NSLog(@"%f",CGPointZero.y);
       // CGPoint p = CGPointMake(self.bounds.size.width,self.bounds.size.height);
        [self.image drawAtPoint:CGPointZero];
        [self.currentTool draw];
    }
    
    // store the image
    self.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

- (id<ACEDrawingTool>)toolWithCurrentSettings
{
    switch (self.drawTool) {
        case ACEDrawingToolTypePen:
        {
            //return [[ACEDrawingPenTool alloc] init];
            return ACE_AUTORELEASE([ACEDrawingPenTool new]);
        }
            
        case ACEDrawingToolTypeLine:
        {
            return ACE_AUTORELEASE([ACEDrawingLineTool new]);
        }
            
        case ACEDrawingToolTypeRectagleStroke:
        {
            ACEDrawingRectangleTool *tool = ACE_AUTORELEASE([ACEDrawingRectangleTool new]);
            tool.fill = NO;
            return tool;
        }
            
        case ACEDrawingToolTypeRectagleFill:
        {
            ACEDrawingRectangleTool *tool = ACE_AUTORELEASE([ACEDrawingRectangleTool new]);
            tool.fill = YES;
            return tool;
        }
            
        case ACEDrawingToolTypeEllipseStroke:
        {
            ACEDrawingEllipseTool *tool = ACE_AUTORELEASE([ACEDrawingEllipseTool new]);
            tool.fill = NO;
            return tool;
        }
            
        case ACEDrawingToolTypeEllipseFill:
        {
            ACEDrawingEllipseTool *tool = ACE_AUTORELEASE([ACEDrawingEllipseTool new]);
            tool.fill = YES;
            return tool;
        }
    }
}


#pragma mark - Touch Methods

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    self.pointArr = [NSMutableArray array];
        self.colseEvent = NO;
        TcpClient *tcp = [TcpClient sharedInstance];
        dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            for(NSString *host in self.hostIdarr){
            [tcp writeString:[Common closeEvent:[host intValue] Metuod:@"CloseShowWindow"]];
            }
        });
    if(self.dropListView.isOpen){
        [self.dropListView hideExtendedChooseView];
    }
    else{
    if (self.drawingMode == DrawingModePainting){
    self.currentTool = [self toolWithCurrentSettings];
    self.currentTool.lineWidth = self.lineWidth;
    self.currentTool.lineColor = self.lineColor;
    self.currentTool.lineAlpha = self.lineAlpha;
    [self.pathArray addObject:self.currentTool];
    // add the first touch
    UITouch *touch = [touches anyObject];
    beginLocation = [touch locationInView:self];
    currentLocation  = [touch locationInView:self];
    [self.currentTool setInitialPoint:[touch locationInView:self]];
        NSLog(@"begin x = %f",currentLocation.x);
        NSLog(@"begin y = %f",currentLocation.y);
    // call the delegate
    if ([self.delegate respondsToSelector:@selector(drawingView:willBeginDrawUsingTool:)]) {
            [self.delegate drawingView:self willBeginDrawUsingTool:self.currentTool];
        }
    if (self.drawingMode == DrawingModePainting){
        TcpClient *tcp = [TcpClient sharedInstance];
        dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            CGPoint p;
            p.x = beginLocation.x * self.zoomX;
            p.y = beginLocation.y * self.zoomY;
            for(NSString *host in self.hostIdarr){
                [tcp writeString:[Common tcpDrawPonitSECstring:[host intValue] Metuod:@"DeviceStartDraw" Fpoint:p Spoint:p Tpoint:p Hpoint:p]];
//                [tcp writeString:[Common tcpDrawPonitBEstring:[host intValue] Metuod:@"DeviceStartDraw" Fpoint:p]];
           // [tcp writeString:[Common tcpDrawXYstring:[host intValue] Metuod:@"DeviceStartDraw" X:(currentLocation.x)*self.zoomX Y:(currentLocation.y)*self.zoomY]];
            }
        });
    }
    }
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    // add the current point to the path
    currentLocation = [touch locationInView:self];
    
    previousLocation = [touch previousLocationInView:self];
    
//    
   // CGPoint mid = [self midPoint:previousLocation P:currentLocation];
//    CGPoint midn = [self midPoint:mid P:currentLocation];
    NSLog(@"previousLocation x = %f",currentLocation.x);
    NSLog(@"previousLocation y = %f",currentLocation.y);
    //

    if (self.drawingMode == DrawingModeNoneing) {
        
        // do nothing
    }
    else if (self.drawingMode == DrawingModePainting) {
        [self.currentTool moveFromPoint:previousLocation toPoint:currentLocation];
//#if PARTIAL_REDRAW
//        // calculate the dirty rect
//        CGFloat minX = fmin(previousLocation.x, currentLocation.x) - self.lineWidth * 0.5;
//        CGFloat minY = fmin(previousLocation.y, currentLocation.y) - self.lineWidth * 0.5;
//        CGFloat maxX = fmax(previousLocation.x, currentLocation.x) + self.lineWidth * 0.5;
//        CGFloat maxY = fmax(previousLocation.y, currentLocation.y) + self.lineWidth * 0.5;
//        [self setNeedsDisplayInRect:CGRectMake(minX, minY, (maxX - minX), (maxY - minY))];
//#else
        [self setNeedsDisplay];
//#endif
//        //发送tcp命令
        NSDictionary *dic = @{@"x":[NSNumber numberWithFloat:currentLocation.x],@"y":[NSNumber numberWithFloat:currentLocation.y]};
        [self.pointArr addObject:dic];
        
//        Point2D cp[] = {{beginLocation.x,beginLocation.y},{previousLocation.x,previousLocation.y},{mid.x,mid.y}};
//        beginLocation.x = mid.x;
//        beginLocation.y = mid.y;
//        int number = 4;
//        Point2D curve[number];
//        
//        ComputeBezier(cp, number, curve); //因为是数组，所以不用加星号。
//        NSLog(@"previousLocation x = %f",previousLocation.x);
//        NSLog(@"previousLocation y = %f",previousLocation.y);
//        
//        NSLog(@"mid x = %f",mid.x);
//        NSLog(@"mid y = %f",mid.y);
//
//        for (int i=0; i<number; i++) {
//            printf("curve[%d].x=%f,curve[%d].y=%f\n",i,curve[i].x,i,curve[i].y);
//            //[arr addObject:(__bridge id)(&curve[i])];
//        }
        if([self.pointArr count] == 3){
            CGPoint fp,sp,tp,hp;//fp1,sp1,tp1,hp1;
//            fp.x = [self.pointArr[0][@"x"] floatValue]*self.zoomX;
//            fp.y = [self.pointArr[0][@"y"] floatValue]*self.zoomY;
//            sp.x = [self.pointArr[1][@"x"] floatValue]*self.zoomX;
//            sp.y = [self.pointArr[1][@"y"] floatValue]*self.zoomY;
//            tp.x = [self.pointArr[2][@"x"] floatValue]*self.zoomX;
//            tp.y = [self.pointArr[2][@"y"] floatValue]*self.zoomY;
       // if(self.isAddPoint){
        Point2D cp[] = {{[self.pointArr[0][@"x"] floatValue],[self.pointArr[0][@"y"] floatValue]},{[self.pointArr[1][@"x"] floatValue],[self.pointArr[1][@"y"] floatValue]},{[self.pointArr[2][@"x"] floatValue],[self.pointArr[2][@"y"] floatValue]}};
////            beginLocation.x = mid.x;
////            beginLocation.y = mid.y;
            int number = 4;
            Point2D curve[number];
            ComputeBezier(cp, number, curve); //因为是数组，所以不用加星号。
            
            fp.x = curve[0].x * self.zoomX;
            fp.y = curve[0].y * self.zoomY;
            sp.x = curve[1].x * self.zoomX;
            sp.y = curve[1].y * self.zoomY;
            tp.x = curve[2].x * self.zoomX;
            tp.y = curve[2].y * self.zoomY;
            hp.x = curve[3].x * self.zoomX;
            hp.y = curve[3].y * self.zoomY;

//            fp.x = [self.pointArr[0][@"x"] floatValue];
//            fp.y = [self.pointArr[0][@"y"] floatValue];
//            sp.x = [self.pointArr[1][@"x"] floatValue];
//            sp.y = [self.pointArr[1][@"y"] floatValue];
//            tp.x = [self.pointArr[2][@"x"] floatValue];
//            tp.y = [self.pointArr[2][@"y"] floatValue];

            
            
//            fp1.x = curve[4].x * self.zoomX;
//            fp1.y = curve[4].y * self.zoomY;
//            sp1.x = curve[5].x * self.zoomX;
//            sp1.y = curve[5].y * self.zoomY;
//            tp1.x = curve[6].x * self.zoomX;
//            tp1.y = curve[6].y * self.zoomY;
//            hp1.x = curve[7].x * self.zoomX;
//            hp1.y = curve[7].y * self.zoomY;
       // }
            TcpClient *tcp = [TcpClient sharedInstance];
 //dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
       // NSArray *arr = [NSArray arrayWithArray:curve];
        for(NSString *host in self.hostIdarr){
       // for (int i=0; i<number; i++) {
        //[tcp writeString:[Common tcpDrawXYstring:[host intValue] Metuod:@"DeviceDoingDraw" X:curve[i].x * self.zoomX Y: curve[i].y *self.zoomY]];
        [tcp writeString:[Common tcpDrawPonitSECstring:[host intValue] Metuod:@"DeviceDoingDraw" Fpoint:fp Spoint:sp Tpoint:tp Hpoint:hp]];
            
          //  [tcp writeString:[Common tcpDrawPonitstring:[host intValue] Metuod:@"DeviceDoingDraw" Fpoint:fp Spoint:sp Tpoint:tp]]; //Hpoint:hp]]; //Fpoint1:fp1 Spoint1:sp1 Tpoint1:tp1 Hpoint1:hp1]];
                }
            [self.pointArr removeAllObjects];
            self.pointArr = [NSMutableArray array];
        }
    }
    else
    {
        
    }
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // make sure a point is recorded
   // [self touchesMoved:touches withEvent:event];
    UITouch *touch = [touches anyObject];
    // add the current point to the path
    currentLocation = [touch locationInView:self];

    if([self.pointArr count] == 1){
        CGPoint tmpp;
       tmpp.x = [self.pointArr[0][@"x"] floatValue]*self.zoomX;
       tmpp.y = [self.pointArr[0][@"y"] floatValue]*self.zoomY;
        TcpClient *tcp = [TcpClient sharedInstance];
        for(NSString *host in self.hostIdarr){
            [tcp writeString:[Common tcpDrawPonitSECstring:[host intValue] Metuod:@"DeviceDoingDraw" Fpoint:tmpp Spoint:tmpp Tpoint:tmpp Hpoint:tmpp]];
        }
        NSLog(@"tmpp_x = %f",tmpp.x);
        NSLog(@"tmpp_y = %f",tmpp.y);
    }
    if([self.pointArr count] == 2){
        CGPoint tmpp1;
        CGPoint tmpp2;
        tmpp1.x = [self.pointArr[0][@"x"] floatValue]*self.zoomX;
        tmpp1.y = [self.pointArr[0][@"y"] floatValue]*self.zoomY;
        tmpp2.x = [self.pointArr[1][@"x"] floatValue]*self.zoomX;
        tmpp2.y = [self.pointArr[1][@"y"] floatValue]*self.zoomY;
        
        NSLog(@"tmpp1_x = %f",tmpp1.x);
        NSLog(@"tmpp1_y = %f",tmpp1.y);
        
        NSLog(@"tmpp2_x = %f",tmpp2.x);
        NSLog(@"tmpp2_y = %f",tmpp2.y);
        
        TcpClient *tcp = [TcpClient sharedInstance];
        for(NSString *host in self.hostIdarr){
            [tcp writeString:[Common tcpDrawPonitSECstring:[host intValue] Metuod:@"DeviceDoingDraw" Fpoint:tmpp1 Spoint:tmpp2 Tpoint:tmpp2 Hpoint:tmpp2]];
        }
    }
    if([self.pointArr count] == 3){
        CGPoint tmpp1;
        CGPoint tmpp2;
        CGPoint tmpp3;
        tmpp1.x = [self.pointArr[0][@"x"] floatValue]*self.zoomX;
        tmpp1.y = [self.pointArr[0][@"y"] floatValue]*self.zoomY;
        tmpp2.x = [self.pointArr[1][@"x"] floatValue]*self.zoomX;
        tmpp2.y = [self.pointArr[1][@"y"] floatValue]*self.zoomY;
        tmpp3.x = [self.pointArr[2][@"x"] floatValue]*self.zoomX;
        tmpp3.y = [self.pointArr[2][@"y"] floatValue]*self.zoomY;
        

        TcpClient *tcp = [TcpClient sharedInstance];
        for(NSString *host in self.hostIdarr){
            [tcp writeString:[Common tcpDrawPonitSECstring:[host intValue] Metuod:@"DeviceDoingDraw" Fpoint:tmpp1 Spoint:tmpp2 Tpoint:tmpp3 Hpoint:tmpp3]];
        }
    }
    if([self.pointArr count] == 4){
        CGPoint tmpp1;
        CGPoint tmpp2;
        CGPoint tmpp3;
        CGPoint tmpp4;
        tmpp1.x = [self.pointArr[0][@"x"] floatValue]*self.zoomX;
        tmpp1.y = [self.pointArr[0][@"y"] floatValue]*self.zoomY;
        tmpp2.x = [self.pointArr[1][@"x"] floatValue]*self.zoomX;
        tmpp2.y = [self.pointArr[1][@"y"] floatValue]*self.zoomY;
        tmpp3.x = [self.pointArr[2][@"x"] floatValue]*self.zoomX;
        tmpp3.y = [self.pointArr[2][@"y"] floatValue]*self.zoomY;
        tmpp4.x = [self.pointArr[3][@"x"] floatValue]*self.zoomX;
        tmpp4.y = [self.pointArr[3][@"y"] floatValue]*self.zoomY;
        
        TcpClient *tcp = [TcpClient sharedInstance];
        for(NSString *host in self.hostIdarr){
            [tcp writeString:[Common tcpDrawPonitSECstring:[host intValue] Metuod:@"DeviceDoingDraw" Fpoint:tmpp1 Spoint:tmpp2 Tpoint:tmpp3 Hpoint:tmpp4]];
        }
    }
    [self.pointArr removeAllObjects];
    //self.pointArr = [NSMutableArray array];
   [self updateCacheImage:NO];
    // clear the current tool
    self.currentTool = nil;
    // clear the redo queue
    [self.bufferArray removeAllObjects];
    if (self.drawingMode == DrawingModePainting){
        TcpClient *tcp = [TcpClient sharedInstance];
        dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            CGPoint p;
            p.x = currentLocation.x * self.zoomX;
            p.y = currentLocation.y * self.zoomY;
            NSLog(@"end_x = %f",p.x);
            NSLog(@"end_y = %f",p.y);
            for(NSString *host in self.hostIdarr){
               [tcp writeString:[Common tcpDrawPonitSECstring:[host intValue] Metuod:@"DeviceEndDraw" Fpoint:p Spoint:p Tpoint:p Hpoint:p]];
//            [tcp writeString:[Common tcpDrawPonitBEstring:[host intValue] Metuod:@"DeviceEndDraw" Fpoint:p]];
//            [tcp writeString:[Common tcpDrawXYstring:[host intValue] Metuod:@"DeviceEndDraw" X:(currentLocation.x)*self.zoomX Y:(currentLocation.y)*self.zoomY]];
            }
        });
    }
        // call the delegate
    if ([self.delegate respondsToSelector:@selector(drawingView:didEndDrawUsingTool:)]) {
        [self.delegate drawingView:self didEndDrawUsingTool:self.currentTool];
    }
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    // make sure a point is recorded
    [self touchesEnded:touches withEvent:event];
}


#pragma mark - Actions

- (void)clear
{
    [self.bufferArray removeAllObjects];
    [self.pathArray removeAllObjects];
    [self updateCacheImage:YES];
    [self setNeedsDisplay];
}


#pragma mark - Undo / Redo

- (NSUInteger)undoSteps
{
    return self.bufferArray.count;
}

- (BOOL)canUndo
{
    return self.pathArray.count > 0;
}

- (void)undoLatestStep
{
    if ([self canUndo]) {
        id<ACEDrawingTool>tool = [self.pathArray lastObject];
        [self.bufferArray addObject:tool];
        [self.pathArray removeLastObject];
        [self updateCacheImage:YES];
        [self setNeedsDisplay];
    }
}

- (BOOL)canRedo
{
    return self.bufferArray.count > 0;
}

- (void)redoLatestStep
{
    if ([self canRedo]) {
        id<ACEDrawingTool>tool = [self.bufferArray lastObject];
        [self.pathArray addObject:tool];
        [self.bufferArray removeLastObject];
        [self updateCacheImage:YES];
        [self setNeedsDisplay];
    }
}

#if !ACE_HAS_ARC

- (void)dealloc
{
    self.pathArray = nil;
    self.bufferArray = nil;
    self.currentTool = nil;
    self.image = nil;
    [super dealloc];
}

#endif
-(void)btnClick:(id)sender
{
        self.colseEvent = NO;
        TcpClient *tcp = [TcpClient sharedInstance];
        dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [tcp writeString:[Common closeEvent:[self.hostIdarr[0] intValue] Metuod:@"CloseShowWindow"]];
        });
    UIButton *btn = (UIButton *)sender;
    if(self.dropListView.isOpen){
        [self.dropListView hideExtendedChooseView];
    }
    else{
        self.dropListView.screenHeight = self.screenHeight;
        self.dropListView.screenWidth = self.screenWidth;
        CGRect r = self.dropListView.frame;
        r.origin.x = btn.frame.origin.x;
        r.origin.y = btn.frame.origin.y+btn.frame.size.height;
       // if(self.forScreenFlag){
            if(btn.frame.size.width < 80){
                r.size.width = 80;
               // r.size.height = btn.frame.size.height;
            }
            else{
                r.size.width = btn.frame.size.width;
            }
        self.dropListView.frame = r;
        self.dropListView.numButton = btn.tag - SECTION_BTN_TAG_BEGIN;
        [self addSubview:self.dropListView];
        [self.dropListView sectionBtnTouch:(UIButton *)sender];
    }
}
-(CGPoint) midPoint:(CGPoint)p1 P:(CGPoint) p2
{
    return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}
Point2D PointOnCubicBezier (Point2D *cp, float t)
{
    float tSquared, tCubed,tst,tct;
    Point2D result;
    tSquared = t * t;
    tCubed = tSquared * t;
    tst = (1-t)*(1-t);
    tct = tst * (1-t);
    result.x = tst*cp[0].x + 2 * t * (1-t) * cp[1].x + tSquared * cp[2].x;
    result.y = tst*cp[0].y + 2 * t * (1-t) * cp[1].y + tSquared * cp[2].y;
    return result;
}

void ComputeBezier (Point2D *cp, int numberOfPoints, Point2D *curve)
{
    float   dt;
    int     i;
    
    dt = 1.0 / ( numberOfPoints -1);
    
    for( i = 0; i < numberOfPoints; i++)
        curve[i] = PointOnCubicBezier( cp, dt*i );
}


@end
